package com.zhengqiangblog.core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Timer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;
import com.zhengqiangblog.blog.cache.common.CacheSupport;
import com.zhengqiangblog.blog.dao.common.DataSourceFactory;
import com.zhengqiangblog.blog.exception.ResourceNotFoundException;
import com.zhengqiangblog.blog.task.PersistArticleViewsTask;

public class Controller extends HttpServlet {

	private static final long serialVersionUID = 1905464720163982577L;

	private static final Logger logger = Logger.getLogger(Controller.class);

	private static final String CHARACTER_ENCODING = "UTF-8";

	private RequestProcesser requestProcesser = ApplicationContext.get(RequestProcesser.class);
	private ResultDispatcher resultDispatcher = ApplicationContext.get(ResultDispatcher.class);
	
	private final static String DOMAIN = PropertiesHelper.get("domain").toString();

	private Timer timer = new Timer();

	@Override
	public void init() throws ServletException {
		super.init();
		startUpTask();
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
		try {
			request.setCharacterEncoding(CHARACTER_ENCODING);
			response.setCharacterEncoding(CHARACTER_ENCODING);
			request.getServletContext().setAttribute("domain", DOMAIN);
			Model model = new Model(request);
			ActionMapping mapping = requestProcesser.mappingRequest(request, model);
			if (mapping == null) {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			Object form = null;
			if (mapping.getActionForm() != null) {
				form = mapping.getActionForm().getConstructor().newInstance();
				requestProcesser.processForm(request, form);
			}
			Class<? extends Object> action = mapping.getAction();
			String actionMethod = mapping.getActionMethod();
			Method method = null;
			Object resultName = null;
			if (form != null) {
				method = action.getDeclaredMethod(actionMethod, Model.class, form.getClass());
				resultName = method.invoke(ApplicationContext.get(action), model, form);
			} else {
				method = action.getDeclaredMethod(actionMethod, Model.class);
				resultName = method.invoke(ApplicationContext.get(action), model);
			}
			Result result = mapping.getResult(resultName.toString());
			resultDispatcher.dispatch(request, response, result, model);
		} catch (Exception e) {
			logger.error("url = " + request.getRequestURL() + ", ip = " + request.getRemoteAddr(), e);
			Throwable cause = e.getCause();
			if (cause instanceof ResourceNotFoundException) {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			if (cause instanceof NumberFormatException) {
				response.sendError(HttpServletResponse.SC_BAD_REQUEST);
				return;
			}
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			return;
		}
	}

	@Override
	public void destroy() {
		CacheSupport.shutDown();
		DataSourceFactory.close();
		try {
			AbandonedConnectionCleanupThread.shutdown();
		} catch (InterruptedException e) {
			logger.error(e.getMessage(), e);
		}
		timer.cancel();
	}

	private void startUpTask() {
		timer.schedule(new PersistArticleViewsTask(), 1 * 60 * 1000, 20 * 60 * 1000);
	}

}
